<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>学生成绩管理系统</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        body {
            background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
            min-height: 100vh;
            padding: 20px;
            color: #333;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
        }

        header {
            text-align: center;
            padding: 30px 0;
            color: white;
            margin-bottom: 30px;
        }

        header h1 {
            font-size: 2.8rem;
            margin-bottom: 10px;
            text-shadow: 0 2px 4px rgba(0,0,0,0.2);
        }

        header p {
            font-size: 1.2rem;
            opacity: 0.9;
            max-width: 600px;
            margin: 0 auto;
        }

        .dashboard {
            display: grid;
            grid-template-columns: 1fr 1.8fr;
            gap: 25px;
            margin-bottom: 30px;
        }

        .card {
            background: white;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.15);
            overflow: hidden;
            padding: 25px;
            transition: transform 0.3s ease;
        }

        .card:hover {
            transform: translateY(-5px);
        }

        .card h2 {
            color: #2c3e50;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #f0f4f8;
            display: flex;
            align-items: center;
        }

        .card h2 i {
            margin-right: 10px;
            color: #3498db;
        }

        .form-group {
            margin-bottom: 18px;
        }

        .form-group label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: #2c3e50;
        }

        .form-control {
            width: 100%;
            padding: 12px 15px;
            border: 2px solid #e1e5eb;
            border-radius: 8px;
            font-size: 1rem;
            transition: border-color 0.3s;
        }

        .form-control:focus {
            border-color: #3498db;
            outline: none;
            box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
        }

        .error-message {
            color: #e74c3c;
            font-size: 0.85rem;
            margin-top: 5px;
            display: block;
            min-height: 20px;
        }

        .btn {
            padding: 12px 25px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-size: 1rem;
            font-weight: 600;
            transition: all 0.3s ease;
            display: inline-flex;
            align-items: center;
            justify-content: center;
        }

        .btn i {
            margin-right: 8px;
        }

        .btn-primary {
            background: #3498db;
            color: white;
        }

        .btn-primary:hover {
            background: #2980b9;
            box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
        }

        .btn-danger {
            background: #e74c3c;
            color: white;
        }

        .btn-danger:hover {
            background: #c0392b;
        }

        .controls {
            display: flex;
            justify-content: space-between;
            margin-bottom: 20px;
            background: #f8f9fa;
            padding: 15px;
            border-radius: 10px;
        }

        .sort-controls {
            display: flex;
            gap: 15px;
            align-items: center;
        }

        .sort-btn {
            background: #ecf0f1;
            color: #2c3e50;
            padding: 8px 15px;
            border-radius: 6px;
            cursor: pointer;
            font-weight: 500;
            transition: all 0.2s;
        }

        .sort-btn.active {
            background: #3498db;
            color: white;
        }

        .sort-btn:hover:not(.active) {
            background: #d6dbdf;
        }

        .student-list-container {
            height: 500px;
            overflow-y: auto;
            border: 2px solid #e1e5eb;
            border-radius: 10px;
            background: white;
            position: relative;
        }

        .student-list {
            position: relative;
        }

        .student-item {
            padding: 18px 20px;
            border-bottom: 1px solid #eee;
            display: flex;
            justify-content: space-between;
            align-items: center;
            transition: background 0.2s;
            cursor: pointer;
        }

        .student-item:hover {
            background: #f8f9fa;
        }

        .student-info {
            display: flex;
            align-items: center;
        }

        .avatar {
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background: #3498db;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: bold;
            font-size: 1.2rem;
            margin-right: 15px;
        }

        .student-name {
            font-weight: 600;
            font-size: 1.1rem;
            color: #2c3e50;
        }

        .student-id {
            color: #7f8c8d;
            font-size: 0.9rem;
            margin-top: 3px;
        }

        .student-scores {
            display: flex;
            gap: 25px;
        }

        .subject-score {
            text-align: center;
            min-width: 70px;
        }

        .subject-name {
            font-size: 0.85rem;
            color: #7f8c8d;
            margin-bottom: 5px;
        }

        .score-value {
            font-weight: 700;
            font-size: 1.1rem;
        }

        .math-score .score-value {
            color: #3498db;
        }

        .english-score .score-value {
            color: #9b59b6;
        }

        .avg-score .score-value {
            color: #2ecc71;
        }

        .delete-btn {
            background: none;
            border: none;
            color: #e74c3c;
            cursor: pointer;
            font-size: 1.2rem;
            padding: 8px;
            opacity: 0.7;
            transition: opacity 0.2s;
        }

        .delete-btn:hover {
            opacity: 1;
        }

        .stats-container {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 20px;
            margin-top: 20px;
        }

        .stat-card {
            background: white;
            border-radius: 12px;
            padding: 20px;
            text-align: center;
            box-shadow: 0 5px 15px rgba(0,0,0,0.1);
        }

        .stat-value {
            font-size: 2.5rem;
            font-weight: 700;
            margin: 10px 0;
        }

        .math-stat .stat-value {
            color: #3498db;
        }

        .english-stat .stat-value {
            color: #9b59b6;
        }

        .avg-stat .stat-value {
            color: #2ecc71;
        }

        .stat-label {
            color: #7f8c8d;
            font-size: 1rem;
        }

        .modal {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.7);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 1000;
            opacity: 0;
            pointer-events: none;
            transition: opacity 0.3s;
        }

        .modal.active {
            opacity: 1;
            pointer-events: all;
        }

        .modal-content {
            background: white;
            border-radius: 15px;
            width: 90%;
            max-width: 500px;
            transform: translateY(20px);
            transition: transform 0.3s;
        }

        .modal.active .modal-content {
            transform: translateY(0);
        }

        .modal-header {
            padding: 20px;
            background: #3498db;
            color: white;
            border-radius: 15px 15px 0 0;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .modal-header h3 {
            font-size: 1.5rem;
        }

        .close-modal {
            background: none;
            border: none;
            color: white;
            font-size: 1.5rem;
            cursor: pointer;
        }

        .modal-body {
            padding: 25px;
        }

        .student-detail {
            display: flex;
            flex-direction: column;
            gap: 20px;
        }

        .detail-row {
            display: flex;
            border-bottom: 1px solid #eee;
            padding-bottom: 15px;
        }

        .detail-label {
            width: 120px;
            font-weight: 600;
            color: #7f8c8d;
        }

        .detail-value {
            flex: 1;
            font-weight: 500;
        }

        .progress-container {
            margin-top: 10px;
            height: 10px;
            background: #ecf0f1;
            border-radius: 5px;
            overflow: hidden;
        }

        .progress-bar {
            height: 100%;
            border-radius: 5px;
        }

        .math-progress {
            background: #3498db;
            width: 90%;
        }

        .english-progress {
            background: #9b59b6;
            width: 85%;
        }

        .avg-progress {
            background: #2ecc71;
            width: 88%;
        }

        @media (max-width: 900px) {
            .dashboard {
                grid-template-columns: 1fr;
            }

            .stats-container {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div id="app" class="container">
        <header>
            <h1><i class="fas fa-graduation-cap"></i> 学生成绩管理系统</h1>
            <p>高效管理学生成绩数据，提供直观的成绩分析和统计功能</p>
        </header>

        <div class="dashboard">
            <div class="card">
                <h2><i class="fas fa-user-plus"></i> 添加新学生</h2>
                <form @submit.prevent="addStudent">
                    <div class="form-group">
                        <label for="name">学生姓名</label>
                        <input type="text" id="name" class="form-control" v-model="newStudent.name" placeholder="请输入学生姓名">
                        <span class="error-message" v-if="errors.name">{{ errors.name }}</span>
                    </div>

                    <div class="form-group">
                        <label for="math">数学成绩</label>
                        <input type="number" id="math" class="form-control" v-model.number="newStudent.math" placeholder="0-100分">
                        <span class="error-message" v-if="errors.math">{{ errors.math }}</span>
                    </div>

                    <div class="form-group">
                        <label for="english">英语成绩</label>
                        <input type="number" id="english" class="form-control" v-model.number="newStudent.english" placeholder="0-100分">
                        <span class="error-message" v-if="errors.english">{{ errors.english }}</span>
                    </div>

                    <button type="submit" class="btn btn-primary">
                        <i class="fas fa-plus"></i> 添加学生
                    </button>
                </form>
            </div>

            <div class="card">
                <h2><i class="fas fa-list"></i> 学生成绩列表</h2>

                <div class="controls">
                    <div class="sort-controls">
                        <span>排序：</span>
                        <div class="sort-btn" :class="{active: sortBy === 'name'}" @click="setSort('name')">
                            姓名 <i class="fas" :class="sortOrder === 'asc' && sortBy === 'name' ? 'fa-arrow-up' : 'fa-arrow-down'"></i>
                        </div>
                        <div class="sort-btn" :class="{active: sortBy === 'math'}" @click="setSort('math')">
                            数学 <i class="fas" :class="sortOrder === 'asc' && sortBy === 'math' ? 'fa-arrow-up' : 'fa-arrow-down'"></i>
                        </div>
                        <div class="sort-btn" :class="{active: sortBy === 'english'}" @click="setSort('english')">
                            英语 <i class="fas" :class="sortOrder === 'asc' && sortBy === 'english' ? 'fa-arrow-up' : 'fa-arrow-down'"></i>
                        </div>
                        <div class="sort-btn" :class="{active: sortBy === 'average'}" @click="setSort('average')">
                            平均分 <i class="fas" :class="sortOrder === 'asc' && sortBy === 'average' ? 'fa-arrow-up' : 'fa-arrow-down'"></i>
                        </div>
                    </div>

                    <div>
                        <span>共 {{ filteredStudents.length }} 名学生</span>
                    </div>
                </div>

                <div class="student-list-container" @scroll="handleScroll">
                    <div class="student-list" :style="{ height: totalHeight + 'px' }">
                        <div v-for="student in visibleStudents" :key="student.id" class="student-item" :style="{ transform: `translateY(${offsetY}px)` }" @click="showStudentDetail(student)">
                            <div class="student-info">
                                <div class="avatar">{{ student.name.charAt(0) }}</div>
                                <div>
                                    <div class="student-name">{{ student.name }}</div>
                                    <div class="student-id">学号: {{ student.id }}</div>
                                </div>
                            </div>

                            <div class="student-scores">
                                <div class="subject-score math-score">
                                    <div class="subject-name">数学</div>
                                    <div class="score-value">{{ student.math }}</div>
                                </div>
                                <div class="subject-score english-score">
                                    <div class="subject-name">英语</div>
                                    <div class="score-value">{{ student.english }}</div>
                                </div>
                                <div class="subject-score avg-score">
                                    <div class="subject-name">平均分</div>
                                    <div class="score-value">{{ student.average.toFixed(1) }}</div>
                                </div>
                            </div>

                            <button class="delete-btn" @click.stop="deleteStudent(student.id)">
                                <i class="fas fa-trash-alt"></i>
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="stats-container">
            <div class="stat-card math-stat">
                <i class="fas fa-calculator fa-2x"></i>
                <div class="stat-value">{{ mathAverage.toFixed(1) }}</div>
                <div class="stat-label">数学平均分</div>
            </div>

            <div class="stat-card english-stat">
                <i class="fas fa-language fa-2x"></i>
                <div class="stat-value">{{ englishAverage.toFixed(1) }}</div>
                <div class="stat-label">英语平均分</div>
            </div>

            <div class="stat-card avg-stat">
                <i class="fas fa-chart-line fa-2x"></i>
                <div class="stat-value">{{ overallAverage.toFixed(1) }}</div>
                <div class="stat-label">总平均分</div>
            </div>
        </div>

        <!-- 学生详情弹窗 -->
        <div class="modal" :class="{active: showDetail}">
            <div class="modal-content">
                <div class="modal-header">
                    <h3>学生详情</h3>
                    <button class="close-modal" @click="closeDetail">
                        <i class="fas fa-times"></i>
                    </button>
                </div>
                <div class="modal-body">
                    <div class="student-detail" v-if="selectedStudent">
                        <div class="detail-row">
                            <div class="detail-label">姓名</div>
                            <div class="detail-value">{{ selectedStudent.name }}</div>
                        </div>
                        <div class="detail-row">
                            <div class="detail-label">学号</div>
                            <div class="detail-value">{{ selectedStudent.id }}</div>
                        </div>
                        <div class="detail-row">
                            <div class="detail-label">数学成绩</div>
                            <div class="detail-value">
                                {{ selectedStudent.math }} 分
                                <div class="progress-container">
                                    <div class="progress-bar math-progress"></div>
                                </div>
                            </div>
                        </div>
                        <div class="detail-row">
                            <div class="detail-label">英语成绩</div>
                            <div class="detail-value">
                                {{ selectedStudent.english }} 分
                                <div class="progress-container">
                                    <div class="progress-bar english-progress"></div>
                                </div>
                            </div>
                        </div>
                        <div class="detail-row">
                            <div class="detail-label">平均分</div>
                            <div class="detail-value">
                                {{ selectedStudent.average.toFixed(1) }} 分
                                <div class="progress-container">
                                    <div class="progress-bar avg-progress"></div>
                                </div>
                            </div>
                        </div>
                        <div class="detail-row">
                            <div class="detail-label">成绩等级</div>
                            <div class="detail-value">
                                <span v-if="selectedStudent.average >= 90" class="text-success">优秀</span>
                                <span v-else-if="selectedStudent.average >= 80" class="text-info">良好</span>
                                <span v-else-if="selectedStudent.average >= 70" class="text-warning">中等</span>
                                <span v-else-if="selectedStudent.average >= 60" class="text-primary">及格</span>
                                <span v-else class="text-danger">不及格</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        new Vue({
            el: '#app',
            data: {
                students: [
                    { id: 1, name: "张三", math: 90, english: 85 },
                    { id: 2, name: "李四", math: 78, english: 92 },
                    { id: 3, name: "王五", math: 88, english: 76 },
                    { id: 4, name: "赵六", math: 65, english: 82 },
                    { id: 5, name: "钱七", math: 92, english: 88 },
                    { id: 6, name: "孙八", math: 72, english: 68 },
                    { id: 7, name: "周九", math: 85, english: 90 },
                    { id: 8, name: "吴十", math: 60, english: 72 },
                    { id: 9, name: "郑十一", math: 95, english: 89 },
                    { id: 10, name: "王小明", math: 82, english: 77 },
                    { id: 11, name: "李小红", math: 79, english: 85 },
                    { id: 12, name: "张伟", math: 87, english: 93 }
                ],
                newStudent: {
                    name: '',
                    math: '',
                    english: ''
                },
                errors: {
                    name: '',
                    math: '',
                    english: ''
                },
                sortBy: 'id',
                sortOrder: 'asc',
                showDetail: false,
                selectedStudent: null,
                // 虚拟滚动相关变量
                itemHeight: 80,
                visibleItemCount: 0,
                startIndex: 0,
                offsetY: 0,
                scrollTop: 0
            },
            computed: {
                // 计算每个学生的平均分
                processedStudents() {
                    return this.students.map(student => ({
                        ...student,
                        average: (student.math + student.english) / 2
                    }));
                },
                // 排序后的学生列表
                filteredStudents() {
                    const sorted = [...this.processedStudents];

                    return sorted.sort((a, b) => {
                        let modifier = 1;
                        if (this.sortOrder === 'desc') modifier = -1;

                        if (this.sortBy === 'name') {
                            return a.name.localeCompare(b.name) * modifier;
                        } else {
                            return (a[this.sortBy] - b[this.sortBy]) * modifier;
                        }
                    });
                },
                // 数学平均分
                mathAverage() {
                    if (this.students.length === 0) return 0;
                    const total = this.students.reduce((sum, student) => sum + student.math, 0);
                    return total / this.students.length;
                },
                // 英语平均分
                englishAverage() {
                    if (this.students.length === 0) return 0;
                    const total = this.students.reduce((sum, student) => sum + student.english, 0);
                    return total / this.students.length;
                },
                // 总平均分
                overallAverage() {
                    if (this.students.length === 0) return 0;
                    const total = this.students.reduce((sum, student) => sum + student.math + student.english, 0);
                    return total / (this.students.length * 2);
                },
                // 虚拟滚动 - 总高度
                totalHeight() {
                    return this.filteredStudents.length * this.itemHeight;
                },
                // 虚拟滚动 - 当前可见的学生
                visibleStudents() {
                    return this.filteredStudents.slice(
                        this.startIndex,
                        this.startIndex + this.visibleItemCount
                    );
                }
            },
            mounted() {
                this.calculateVisibleItems();
                window.addEventListener('resize', this.calculateVisibleItems);
            },
            beforeDestroy() {
                window.removeEventListener('resize', this.calculateVisibleItems);
            },
            methods: {
                // 添加学生
                addStudent() {
                    // 验证表单
                    this.errors = { name: '', math: '', english: '' };
                    let valid = true;

                    if (!this.newStudent.name.trim()) {
                        this.errors.name = '请输入学生姓名';
                        valid = false;
                    }

                    if (this.newStudent.math === '' || this.newStudent.math < 0 || this.newStudent.math > 100) {
                        this.errors.math = '请输入0-100之间的分数';
                        valid = false;
                    }

                    if (this.newStudent.english === '' || this.newStudent.english < 0 || this.newStudent.english > 100) {
                        this.errors.english = '请输入0-100之间的分数';
                        valid = false;
                    }

                    if (!valid) return;

                    // 生成新学生ID
                    const newId = this.students.length > 0
                        ? Math.max(...this.students.map(s => s.id)) + 1
                        : 1;

                    // 添加新学生
                    this.students.push({
                        id: newId,
                        name: this.newStudent.name,
                        math: Number(this.newStudent.math),
                        english: Number(this.newStudent.english)
                    });

                    // 重置表单
                    this.newStudent = { name: '', math: '', english: '' };
                },
                // 删除学生
                deleteStudent(id) {
                    this.students = this.students.filter(student => student.id !== id);
                },
                // 设置排序方式
                setSort(field) {
                    if (this.sortBy === field) {
                        this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
                    } else {
                        this.sortBy = field;
                        this.sortOrder = 'asc';
                    }
                },
                // 显示学生详情
                showStudentDetail(student) {
                    this.selectedStudent = student;
                    this.showDetail = true;
                },
                // 关闭详情弹窗
                closeDetail() {
                    this.showDetail = false;
                },
                // 计算可见项数量
                calculateVisibleItems() {
                    const container = document.querySelector('.student-list-container');
                    if (!container) return;

                    this.visibleItemCount = Math.ceil(container.clientHeight / this.itemHeight) + 2;
                    this.handleScroll();
                },
                // 处理滚动事件
                handleScroll() {
                    const container = document.querySelector('.student-list-container');
                    if (!container) return;

                    this.scrollTop = container.scrollTop;
                    this.startIndex = Math.floor(this.scrollTop / this.itemHeight);
                    this.offsetY = this.startIndex * this.itemHeight;
                }
            }
        });
    </script>
</body>
</html>